package com.ztesoft.report.service.impl;

import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ztesoft.report.base.pojo.R;
import com.ztesoft.report.base.service.impl.BaseServiceImpl;
import com.ztesoft.report.dao.SysSqlDao;
import com.ztesoft.report.entity.Datasource;
import com.ztesoft.report.entity.ReportData;
import com.ztesoft.report.dao.ReportDataDao;
import com.ztesoft.report.entity.SysSql;
import com.ztesoft.report.exception.RException;
import com.ztesoft.report.service.DataService;
import com.ztesoft.report.service.DatasourceService;
import com.ztesoft.report.service.ReportDataService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author y3tu
 * @since 2018-06-15
 */
@Service
@Slf4j
public class ReportDataServiceImpl extends BaseServiceImpl<ReportDataDao, ReportData> implements ReportDataService {
    @Autowired
    private ReportDataDao reportDataDao;

    @Autowired
    DatasourceService datasourceService;

    @Autowired
    SysSqlDao sysSqlDao;

    @Autowired
    DataService dataService;

    @Override
    public R queryPage1(Map<String, Object> map) {
        int current = (int) map.get("current");
        int size = (int) map.get("size");
        PageHelper.startPage(current, size);
        List<ReportData> list = null;
        list = reportDataDao.queryPage1(map);
        PageInfo<ReportData> page = new PageInfo<>(list);
        return R.ok(page);
    }

    @Override
    public R totalRun(ReportData reportData) {
        if (reportData != null) {
            String sqls = reportData.getSqls();
            String params = reportData.getParams();
            List<Map<String, String>> doneSqls = null;
            try {
                doneSqls = handleSql(sqls, params);
            } catch (Exception e) {
                log.error("",e);
                throw new RException("未获取到此生成数据的实例");
            }
                List<Connection> conns = null;
                try {
                    conns = dataService.executeSql(doneSqls);
                } catch (Exception e) {
                    log.error("", e);
                    throw new RException("SQL执行异常，请检查！");
                }
        } else {
            throw new RException("传入数据生成ID有误！");
        }

        return R.ok();
    }

    /**
     * @param sqls         json类型字符串，sql集
     * @param params       json类型字符串，参数集
     * @return 处理好的sql集合，可以直接执行 sql 可以执行sql ，dataSourceId 为对应数据源
     */
    private List<Map<String, String>> handleSql( String sqls, String params) {
        List<Map<String, String>> doneSqls = new LinkedList<>();
        List<Map<String, Object>> sqlList = JSON.parseObject(sqls, List.class);
        List<Map<String, String>> paramlist = JSON.parseObject(params, List.class);
        for (Map<String, Object> mapSql : sqlList) {
            String sql = mapSql.get("value").toString();
            String dsID = mapSql.get("dataSourceId").toString();
            //设置一个处理{{}}的次数，防止因为异常无法替换而造成的死循环
            int count = 0;
            while (sql.contains("{{")) {
                if (count > 100) {
                    throw new RException("{{}}替换异常,请检查SQL");
                }
                log.info("处理前SQL："+sql);
                sql = cleanSql(sql , paramlist);
                log.info("处理后SQL："+sql);
                count++;
            }
            Map<String, String> sqlAndDsID = new HashMap<>();
            sqlAndDsID.put("sql",sql);
            sqlAndDsID.put("dataSourceId",dsID);
            doneSqls.add(sqlAndDsID);
        }
        return doneSqls;
    }

    /**
     * 替换掉所有{{}}
     * @return sql
     */
    private String cleanSql(String sql, List<Map<String, String>> paramlist) {
        //获取{{key}},这个key,然后去参数List找到对应的做相应处理
        String key = sql.substring(sql.indexOf("{{") + 2, sql.indexOf("}}")).trim();
        log.info("需要处理{{key}}中这个key为："+key);
        for (Map<String, String> mapParams : paramlist) {
            if (key.equals(mapParams.get("key"))) {
                //根据type的3种类型做出不同的处理
                switch (mapParams.get("type")) {
                    case "1":
                        sql = sql.replace("{{" + key + "}}",mapParams.get("value"));
                        break;
                    case "2":
                        SysSql sysSql2 = new SysSql();
                        sysSql2.setSqlCode(mapParams.get("dataCode"));
                        SysSql sysSqlResult2 = sysSqlDao.getSelectListBySqlCode(sysSql2);
                        String dataSourceID = sysSqlResult2.getDatasourceId().toString();
                        List<Map> listType2 = dataService.executeQuerySql(dataSourceID,
                                "select value from SYS_DICT_ITEM where dict_code= '" + mapParams.get("dataCode") + "' and name = '" + mapParams.get("value") + "'");
                        if (listType2 != null && listType2.size() > 0) {
                            sql = sql.replace("{{" + key + "}}", listType2.get(0).get("VALUE").toString());
                        }
                        break;
                    case "3":
                        SysSql sysSql3 = new SysSql();
                        sysSql3.setSqlCode(mapParams.get("dataCode"));
                        SysSql sysSqlResult3 = sysSqlDao.getSelectListBySqlCode(sysSql3);
                        String dataSourceID3 = sysSqlResult3.getDatasourceId().toString();
                        List<Map> listType3 = dataService.executeQuerySql(dataSourceID3,
                                "select sql_text,datasource_id from SYS_SQL where sql_code = '" + mapParams.get("dataCode") + "'");
                        if (listType3 != null && listType3.size() > 0) {
                            String text = listType3.get(0).get("SQL_TEXT").toString();
                            List<Map> textList = dataService.executeQuerySql(dataSourceID3, text);
                            if (textList != null && textList.size() > 0) {
                                //替换，比如{{yyyyMM}} ---->> 201801 这里注意没加引号 直接替换，如果到时候有需求再优化代码
                                sql = sql.replace("{{" + key + "}}",  textList.get(0).get(mapParams.get("value")).toString());

                            }
                        }
                }
            }
        }
        return sql;
    }
}
